package org.stayfool.auth.context;

import java.io.File;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.stayfool.auth.service.AuthService;

@Component
public class ControllerUrlScaner {

	private final Logger log = LoggerFactory.getLogger(getClass());

	@Resource(name = "authService")
	private AuthService authService;

	// 初始化web URL资源
	@PostConstruct
	public void initWebResources() {
		ClassLoader cl = Thread.currentThread().getContextClassLoader();
		System.out.println(cl.getResource("").getPath());
		List<Class<?>> classList = new ArrayList<>();

		loadClass(cl, cl.getResource("").getPath(), classList);

		saveUrlAsResource(classList);
	}

	private void loadClass(ClassLoader cl, String path, List<Class<?>> classList) {
		path = clearPath(path);
		File file = new File(path);
		if (file.isDirectory()) {
			for (String subPath : file.list()) {
				loadClass(cl, path + "/" + subPath, classList);
			}
		} else {
			if (file.getName().endsWith(".class")) {
				String fullName = path;
				fullName = fullName.substring(cl.getResource("").getPath().length());
				fullName = fullName.substring(0, fullName.lastIndexOf("."));
				fullName = fullName.replaceAll("\\\\", ".").replaceAll("/", ".");
				try {
					classList.add(cl.loadClass(fullName));
					log.error("load class " + fullName + " success");
				} catch (ClassNotFoundException e) {
					log.error("load class " + fullName + " failed");
					e.printStackTrace();
				}
			}
		}
	}

	private void saveUrlAsResource(List<Class<?>> classList) {
		classList.stream()
				.filter(c -> c.isAnnotationPresent(Controller.class) || c.isAnnotationPresent(RestController.class))
				.forEach(c -> {
					String baseUrl = "";
					RequestMapping cr = c.getAnnotation(RequestMapping.class);
					if (hasPath(cr))
						baseUrl = cr.value()[0];

					final String url = baseUrl;
					Arrays.asList(c.getDeclaredMethods()).stream()
							.filter(m -> m.isAnnotationPresent(RequestMapping.class)).filter(m -> hasPath(m))
							.forEach(m -> {
								RequestMapping mr = m.getAnnotation(RequestMapping.class);
								String fullUrl = url + mr.value()[0];
								authService.saveIfAbsent(fullUrl);
							});
				});
	}

	private String clearPath(String path) {
		if (path.startsWith("/"))
			path = path.substring(1);
		return path;
	}

	private boolean hasPath(RequestMapping r) {
		return r != null && r.value() != null && r.value().length > 0;
	}

	private boolean hasPath(Method m) {
		return hasPath(m.getAnnotation(RequestMapping.class));
	}
}
